import os
import getpass
import json
import shutil

from PySide2.QtWidgets import *
from PySide2.QtGui import QFont

from CustWidgets import PasswordDialog


class CreateDataStreamDialog(QDialog):

    def __init__(self, config, parent=None):
        super(CreateDataStreamDialog, self).__init__(parent=parent)
        self.config = config
        
        self.username = getpass.getuser()
        eii_dep_tool_cfg_dir = os.path.join("/home/{}/.eii".format(self.username))
        os.makedirs(eii_dep_tool_cfg_dir, exist_ok=True)
        self.eii_dep_tool_cfg_file = os.path.join(eii_dep_tool_cfg_dir, "eii_deploy_tool.cfg")
        
        self.init_ui()
        self.signals_collector()

    def init_ui(self):
        self.setWindowTitle("Create New Data Stream")
        self.resize(500, 220)
        self.grid_lyt_global = QGridLayout(self)

        # Font for tips
        title_font = QFont()
        title_font.setPointSize(12)
        title_font.setBold(True)
        title_font.setItalic(True)
        title_font.setWeight(75)

        # Tip for setting working directory
        self.lbl_working_dir = QLabel(self)
        self.lbl_working_dir.setText("Select EII Home")
        self.lbl_working_dir.setFont(title_font)
        self.grid_lyt_global.addWidget(self.lbl_working_dir, 0, 0, 1, 5)
        # Widget for setting working directory
        self.wgt_working_dir = QWidget(self)
        self.grid_lyt_working_dir = QGridLayout(self.wgt_working_dir)
        self.hbox_lyt_working_dir = QHBoxLayout()
        # LineEdit for showing setted working directory
        self.le_working_dir = QLineEdit(self.wgt_working_dir)
        self.le_working_dir.setPlaceholderText("Select EII \"IEdgeInsights\" directory as EII Home")
        self.le_working_dir.setReadOnly(True)
        if os.path.exists(self.eii_dep_tool_cfg_file):
            with open(self.eii_dep_tool_cfg_file, "r") as f:
                content = f.read()
                if content:
                    content_dict = json.loads(content)
                    if "eii_home" in content_dict.keys():
                        self.le_working_dir.setText(content_dict["eii_home"])
        self.hbox_lyt_working_dir.addWidget(self.le_working_dir)
        # Button for opening working directory
        self.btn_working_dir = QPushButton(self.wgt_working_dir)
        self.btn_working_dir.setText("...")
        sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.btn_working_dir.sizePolicy().hasHeightForWidth())
        self.btn_working_dir.setSizePolicy(sizePolicy)
        self.hbox_lyt_working_dir.addWidget(self.btn_working_dir)
        self.grid_lyt_working_dir.addLayout(self.hbox_lyt_working_dir, 0, 0, 1, 1)
        self.grid_lyt_global.addWidget(self.wgt_working_dir, 1, 0, 1, 5)

        # Tip for choosing project mode
        self.lbl_project_mode = QLabel(self)
        self.lbl_project_mode.setText("Input Data Stream Name")
        self.lbl_project_mode.setFont(title_font)
        self.grid_lyt_global.addWidget(self.lbl_project_mode, 2, 0, 1, 5)
        # Widget for project mode
        self.wgt_project_mode = QWidget(self)
        self.grid_lyt_project_mode = QGridLayout(self.wgt_project_mode)

        # Frame for storing project mode
        self.frm_project_mode = QFrame(self.wgt_project_mode)
        self.frm_project_mode.setFrameShape(QFrame.StyledPanel)
        self.frm_project_mode.setFrameShadow(QFrame.Raised)
        self.grid_lyt_frm = QGridLayout(self.frm_project_mode)
        self.form_lyt_frm = QFormLayout()
        # Project Name
        self.lbl_project_name = QLabel(self.frm_project_mode)
        self.lbl_project_name.setText("Data Stream Name")
        self.form_lyt_frm.setWidget(0, QFormLayout.LabelRole, self.lbl_project_name)
        self.le_project_name = QLineEdit(self.frm_project_mode)
        self.form_lyt_frm.setWidget(0, QFormLayout.FieldRole, self.le_project_name)
        
        # Layout of frame
        self.grid_lyt_frm.addLayout(self.form_lyt_frm, 0, 0, 1, 1)
        # Layout of project mode
        self.grid_lyt_project_mode.addWidget(self.frm_project_mode, 1, 0, 1, 3)
        # Global layout
        self.grid_lyt_global.addWidget(self.wgt_project_mode, 3, 0, 1, 5)

        # Spacers
        spacerItem1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        self.grid_lyt_global.addItem(spacerItem1, 4, 0, 1, 1)
        spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        self.grid_lyt_global.addItem(spacerItem, 4, 2, 1, 1)
        spacerItem2 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        self.grid_lyt_global.addItem(spacerItem2, 4, 4, 1, 1)
        # Cancel button
        self.btn_cancel = QPushButton(self)
        self.btn_cancel.setText("&Cancel")
        self.grid_lyt_global.addWidget(self.btn_cancel, 4, 1, 1, 1)
        # Next button
        self.btn_next = QPushButton(self)
        self.btn_next.setText("&Next")
        self.btn_next.setDefault(True)
        self.btn_next.setAutoDefault(True)
        self.grid_lyt_global.addWidget(self.btn_next, 4, 3, 1, 1)

    def slot_set_working_dir(self):
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        options |= QFileDialog.ShowDirsOnly
        selected_dir = str(QFileDialog.getExistingDirectory(
            None, "Select Directory", "/home/{}".format(self.username), options=options))
        # Only the selected directory is not an empty string
        if selected_dir != "":
            self.le_working_dir.setText(selected_dir)

    def _show_msg_dialog(self, text):
        QMessageBox.warning(self, "Warning", "{}".format(text), QMessageBox.Ok)

    def slot_btn_next(self):
        # Check all the input items
        if not self.le_working_dir.text():
            self._show_msg_dialog("\"EII Home Path\" cannot be empty.")
            return
        if not self.le_project_name.text():
            self._show_msg_dialog("\"Data Stream Name\" cannot be empty.")
            return

        # Save hidden config file
        if not os.path.exists(self.eii_dep_tool_cfg_file):
            with open(self.eii_dep_tool_cfg_file, "w") as f:
                content = {
                    "eii_home": self.le_working_dir.text()
                }
                content_json = json.dumps(content, indent=4)
                f.write(content_json + "\n")
        else:
            with open(self.eii_dep_tool_cfg_file, "w+") as f:
                content = f.read()
                if content:
                    content_dict = json.loads(content)
                else:
                    content_dict = {}
                content_dict["eii_home"] = self.le_working_dir.text()
                content_json = json.dumps(content_dict, indent=4)
                f.write(content_json + "\n")

        # Get user password
        tmp = {}
        pwd_dialog = PasswordDialog(config=tmp)
        pwd_dialog.show()
        pwd_dialog.exec_()
        if "pwd" not in tmp.keys():
            return
        pwd = tmp["pwd"]

        # Project Info
        data_stream_name = self.le_project_name.text()

        # Create eii_helper/workspace folder in EII Home if not exist
        dst_eii_helper_ws = os.path.join(self.le_working_dir.text(), "eii_helper", "workspace")
        os.makedirs(dst_eii_helper_ws, exist_ok=True)
        
        # Create data stream in eii_helper/workspace
        ds_path = os.path.join(dst_eii_helper_ws, data_stream_name)
        if os.path.exists(ds_path):
            res = QMessageBox.warning(self, "Warning", 
                "The data stream, \"{}\", has existed. Overwrite it?".format(data_stream_name), 
                QMessageBox.No | QMessageBox.Yes)
            if res == QMessageBox.No:
                return
            shutil.rmtree(ds_path)
        os.makedirs(ds_path)

        # Update config
        self.config["eii_home"] = self.le_working_dir.text()
        self.config["project_name"] = self.le_project_name.text()
        self.config["host_pwd"] = pwd

        self.close()

    def signals_collector(self):
        self.btn_working_dir.clicked.connect(self.slot_set_working_dir)
        self.btn_cancel.clicked.connect(self.close)
        self.btn_next.clicked.connect(self.slot_btn_next)
